#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//用于判断整形数据的大小的函数
int cmp_int(const void* e1, const void* e2)    
{
    return (*(int *)e1-*(int *)e2);
}

//用于判断字符型数据的大小的函数
int cmp_char(const void* e1, const void* e2)
{
    //strcmp的返回值大小，a>b返回1；a=b返回0；a<b返回-1
    return strcmp((char*)e1, (char*)e2);
}

//用于交换两个元素的函数
void Swap(char* buf1,char* buf2,int width)
{
    int i = 0;
    for ( i = 0; i < width; i++)
    {
        char tmp = *buf1;
        *buf1 = *buf2;
        *buf2 = tmp;
        buf1++;
        buf2++;
    }
    
}
//使用回调函数实现任意数据的冒泡排序
//base为需要对比的元素的首地址
//sz为需要对比的元素个数
//width为需要对比的元素大小，单位为字节
//int(*cmp)(const void* e1, const void* e2)为函数指针，指向需要调用的比较函数,cmp为形参名

void bubble_sort(void* base, int sz, int width, int(*cmp)(const void* e1, const void* e2))
{
    int i = 0;
    int j = 0; 
    for ( i = 0; i < sz-1; i++)
    {
        int flag = 1;
        for ( j = 0; j < sz-1-i; j++)
        {
            if(cmp((char *)base+j*width,(char *)base+(j+1)*width) > 0)       //传参对比j和j+1元素的大小，base类型为void*，需要转换类型
            {
                Swap((char *)base+j*width,(char *)base+(j+1)*width,width);
                flag = 0;
            }
        }
        if(1 == flag)
        {
            break;
        }
    }
}

//测试整形数据排序函数
void test1()
{
    int i = 0;
    int arr[] = {9,8,7,6,5,4,3,2,1};
    int sz = sizeof(arr)/sizeof(arr[0]);
    bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
    for(i = 0; i < sz; i++)
    {
        printf("%d ",arr[i]);
    }
}

//测试字符型数据排序函数
void test2()
{
    int i = 0;
    char arr[] = "fedcba";
    int sz = sizeof(arr)/sizeof(arr[0]);
    bubble_sort(arr, sz, sizeof(arr[0]), cmp_char);
    for(i = 0; i < sz; i++)
    {
        printf("%c ",arr[i]);
    }
}

int main(){
    test1();
    test2();
    return 0;
}